#!/usr/bin/perl

use DBI;
use POSIX;
use strict;

my $output_debug=0;
# get our our command line arguments
for (my $i=0;$i<=$#ARGV;$i++){
    if ($ARGV[$i] eq "-D"){
	# level up debug printing
	$output_debug++;
    }
}

# database details
my $dsn="dbi:Pg:dbname=atca;host=mentok;port=5432";
my $user="postgres";
my $password="";

# Setup the database connection
my $dbh=DBI->connect($dsn,$user,$password,{ RaiseError => 0, AutoCommit => 1});

# Get a list of all the files in the correlator log directories
my @correlator_logfiles;
my @correlator_log_directories=("/data/MENTOK_2/ste616/flux_monitoring/data/corr_logs/caccc0/",
				"/data/MENTOK_2/ste616/flux_monitoring/data/corr_logs/caccc1/");
@correlator_logfiles=&list_directories("cor_*.log",@correlator_log_directories);

if ($output_debug>1){
    for (my $i=0;$i<=$#correlator_logfiles;$i++){
	print "logfile $i: $correlator_logfiles[$i]\n";
    }
}

# get the time of the latest event in the database
my $lte_query="SELECT event_time FROM events ORDER BY event_time DESC LIMIT 1";
if ($output_debug>1){
    print "query: $lte_query\n";
}
my $lte=$dbh->prepare($lte_query);
$lte->execute;
my $latest_time;
while (my @lte_response=$lte->fetchrow()){
    $latest_time=$lte_response[0];
}
$lte->finish;
my $unt_latest_time=&time_to_unixtime($latest_time);

# go through the correlator log files
for (my $i=0;$i<=$#correlator_logfiles;$i++){
    # check that this file hasn't already been summarised
    my $summarise=1;
    my $corlog=$correlator_logfiles[$i];
    $corlog=~s/^.*\/([^\/]*)$/$1/;
    my $checked=&check_corlog($dbh,$corlog);
    if ($checked>0){
	# check that the whole file has been summarised already
	my $time_last=&last_time($correlator_logfiles[$i]);
	my $unt_time_last=&time_to_unixtime($time_last);
	if ($unt_time_last<=$unt_latest_time){
	    # this file will have been summarised already
	    $summarise=0;
	    if ($output_debug>0){
		print "already parsed correlator logfile $correlator_logfiles[$i]\n";
	    }
	}
    }
    if ($summarise==1){
	# parse this file
	if ($output_debug>0){
	    print "parsing correlator logfile $correlator_logfiles[$i]\n";
	}
	# get the year this log starts in
	my $year=$corlog;
	$year=~s/^cor\_(.*?)\-.*/$1/;
	if ($output_debug>1){
	    print "log starts in year $year\n";
	}
	open(LOG,$correlator_logfiles[$i]);
	my $old_month=-1;
	my ($current_source,$current_freqinfo,$current_rpfits);
	while(<LOG>){
	    chomp;
	    my $line=$_;
	    # split the line into its parts
	    $line=~/^(.*?)\-(.*?)\s(.*?)\:\:\s(.*)$/;
	    # form the date - the correlator only logs month and day and UT time
	    my ($month,$day,$ut_time,$activity)=($1,$2,$3,$4);
	    if (($month<$old_month)&&($old_month==12)&&($month==1)){
		$year++;
	    }
	    $old_month=$month;
	    my $event_time=$year."-".$month."-".$day." ".$ut_time;
	    # check if this event time is after the last time in the database
	    my $unt_event_time=&time_to_unixtime($event_time);
	    if ($unt_event_time<=$unt_latest_time){
		# should have been summarised already
		next;
	    }
	    # now look for recognised events
	    if ($activity=~/^CACOR/){
		# the correlator has started
		# there is one argument, the correlator version
		$activity=~/^CACOR\s+Version\s(.*?)\s.*/;
		my $version=$1;
		# stick this info into the database
		&add_event($dbh,"correlator_start",$event_time,1,$version,"",0,"",$corlog);
	    } elsif ($activity=~/^CCOMMAND\:/){
		# we have a correlator command
		$activity=~/^CCOMMAND\:\s+\'\s*(.*?)\'$/;
		my $ccommand=$1;
		if ($ccommand=~/.*\sa$/){
		    # the command was applied - these are the only commands we
		    # really care about
		    my @els=split(/\s+/,$ccommand);
		    my @add_event_args;
		    push @add_event_args,$dbh;
		    push @add_event_args,$els[0];
		    push @add_event_args,$event_time;
		    my $nargs=($#els+1)-2;
		    push @add_event_args,$nargs;
		    if ($nargs>0){
			for (my $j=1;$j<$#els;$j++){
			    push @add_event_args,$els[$j];
			}
		    }
		    push @add_event_args,$current_source;
		    my @ifinfo=&split_freqinfo($current_freqinfo);
		    my $nifs=$#ifinfo+1;
		    push @add_event_args,$nifs;
		    if ($nifs>0){
			for (my $j=0;$j<=$#ifinfo;$j++){
			    push @add_event_args,$ifinfo[$j];
			}
		    }
		    push @add_event_args,$current_rpfits;
		    push @add_event_args,$corlog;
		    # stick the info into the database
		    &add_event(@add_event_args);
		    undef @add_event_args;
		}
	    } elsif ((($activity=~/1A\:\sCorrections\:/)||
		      ($activity=~/1A\:\s NCal\s\(Jy\)\:/))&&
		     (($year<=2009)&&($month<=07)&&($day<=23))){
		# the correlator didn't always make it easy for us!
		$activity=~/(.*)\s1A\:(.*)/;
		my $ccommand=$1;
		$ccommand=~tr/A-Z/a-z/;
		my @add_event_args;
		push @add_event_args,$dbh;
		push @add_event_args,$ccommand;
		push @add_event_args,$event_time;
		my $nargs=0;
		push @add_event_args,$nargs;
		push @add_event_args,$current_source;
		my @ifinfo=&split_freqinfo($current_freqinfo);
		my $nifs=$#ifinfo+1;
		push @add_event_args,$nifs;
		if ($nifs>0){
		    for (my $j=0;$j<=$#ifinfo;$j++){
			push @add_event_args,$ifinfo[$j];
		    }
		}
		push @add_event_args,$current_rpfits;
		push @add_event_args,$corlog;
		# stick the info into the database
		&add_event(@add_event_args);
		undef @add_event_args;
	    } elsif ($activity=~/^HDR\:/){
		# details about the current source, we keep track of these
		# for later use
		$activity=~/^HDR\:\sSrc\:(.*)\sFq\:(.*)$/;
		$current_source=$1;
		$current_freqinfo=$2;
		$current_source=~s/\s//g;
	    } elsif ($activity=~/^CORDAT\:/){
		# a file has been opened or closed
		if ($activity=~/CLOSED$/){
		    # closed the RPFITS file
		    $current_rpfits="";
		} elsif ($activity=~/OPENED/){
		    $current_rpfits=$activity;
		    $current_rpfits=~s/(.*)\:\s(.*)$/$2/;
		}
	    } elsif ($activity=~/^SYNCCC\:/){
		# something has happened, but we're only interested in when
		# the correlator has exited
		if ($activity=~/QUIT/){
		    &add_event($dbh,"correlator_stop",$event_time,0,"",0,"",$corlog);
		}
	    } elsif ($activity=~/^CONFIG\s/){
		# the correlator config has been changed
		$activity=~/^CONFIG\s(.*)/;
		my $config=$1;
		&add_event($dbh,"config_change",$event_time,1,$config,"",0,"",$corlog);
	    } elsif ($activity=~/DELAY\sJUMP\./){
		# the correlator may have glitched
		my @ifinfo=&split_freqinfo($current_freqinfo);
		my $nifs=$#ifinfo+1;
		my @add_event_args;
		push @add_event_args,$dbh;
		push @add_event_args,"delay_jump";
		push @add_event_args,$event_time;
		push @add_event_args,0;
		push @add_event_args,$current_source;
		push @add_event_args,$nifs;
		if ($nifs>0){
		    for (my $j=0;$j<=$#ifinfo;$j++){
			push @add_event_args,$ifinfo[$j];
		    }
		}
		push @add_event_args,$current_rpfits;
		push @add_event_args,$corlog;
		# stick the info into the database
		&add_event(@add_event_args);
		undef @add_event_args;
	    } elsif ($activity=~/^RESET/){
		# a reset command was issued
		$activity=~tr/A-Z/a-z/;
		$activity=~s/\s+/_/g;
		my @ifinfo=&split_freqinfo($current_freqinfo);
		my $nifs=$#ifinfo+1;
		my @add_event_args;
		push @add_event_args,$dbh;
		push @add_event_args,$activity;
		push @add_event_args,$event_time;
		push @add_event_args,0;
		push @add_event_args,$current_source;
		push @add_event_args,$nifs;
		if ($nifs>0){
		    for (my $j=0;$j<=$#ifinfo;$j++){
			push @add_event_args,$ifinfo[$j];
		    }
		}
		push @add_event_args,$current_rpfits;
		push @add_event_args,$corlog;
		# stick the info into the database
		&add_event(@add_event_args);
		undef @add_event_args;
	    }
	}
	close(LOG);
    }
}

# disconnect from the database
$dbh->disconnect;

sub time_to_unixtime {
    my ($ptime)=@_;
    
    $ptime=~/^(\d{4})\-(\d{2})\-(\d{2})\s(\d{2})\:(\d{2})\:(\d{2})/;
    my ($year,$month,$day,$hour,$minute,$second)=($1,$2,$3,$4,$5,$6);
    $year-=1900;
    $month-=1;

    my $utime=mktime($second,$minute,$hour,$day,$month,$year,0,0);

    return $utime;
}

sub split_freqinfo {
    # split a correlator frequency string into its parts
    my $freqinfo=$_[0];
    my @ifs=split(/\s+/,$freqinfo);
    for (my $i=0;$i<=$#ifs;$i++){
	$ifs[$i]=~s/^(.*)\/(.*)$/$1/;
    }
    return @ifs;
}

sub add_event {
    # get the right arguments
    my @args=@_;
    my $dbh=shift @args;
    my $event_type=shift @args;
    my $event_time=shift @args;
    my $num_args=shift @args;
    my @theargs;
    for (my $i=0;$i<$num_args;$i++){
	push @theargs,shift @args;
    }
    my $event_source=shift @args;
    my $num_ifs=shift @args;
    my @if_freqs;
    for (my $i=0;$i<$num_ifs;$i++){
	push @if_freqs,shift @args;
    }
    my $rpfits_file=shift @args;
    my $cor_log=shift @args;

    my $ins_query="INSERT INTO events VALUES('".$event_type."','".$event_time."',".
	$num_args.",'{";
    if ($num_args==0){
	$ins_query.="NULL";
    } else {
	for (my $i=0;$i<$num_args;$i++){
	    if ($i!=0){
		$ins_query.=",";
	    }
	    $ins_query.="\"".$theargs[$i]."\"";
	}
    }
    $ins_query.="}',";
    if ($event_source eq ""){
	$ins_query.="NULL";
    } else {
	$ins_query.="'".$event_source."'";
    }
    $ins_query.=",".$num_ifs.",'{";
    if ($num_ifs==0){
	$ins_query.="NULL";
    } else {
	for (my $i=0;$i<$num_ifs;$i++){
	    if ($i!=0){
		$ins_query.=",";
	    }
	    $ins_query.=$if_freqs[$i];
	}
    }
    $ins_query.="}',";
    if ($rpfits_file eq ""){
	$ins_query.="NULL";
    } else {
	$ins_query.="'".$rpfits_file."'";
    }
    $ins_query.=",'".$cor_log."')";
    if ($output_debug>0){
	print "$ins_query\n";
    }
    # now actually insert the data
    my $ins=$dbh->prepare($ins_query);
    $ins->execute;
    $ins->finish;
}

sub check_corlog {
    my ($dbh,$corlog)=@_;
    my $chk_query="SELECT cor_log FROM events WHERE cor_log='".$corlog."' LIMIT 1";
    if ($output_debug>1){
	print "query: $chk_query\n";
    }
    my $chk=$dbh->prepare($chk_query);
    $chk->execute;
    my $nresults=0;
    while (my ($logcor)=$chk->fetchrow()){
	$nresults++;
    }
    $chk->finish;
    if ($output_debug>1){
	print "found $nresults results\n";
    }
    return $nresults;
}

sub list_directories {
    my ($pattern,@directories)=@_;
    my @listing;

    for (my $i=0;$i<=$#directories;$i++){
	my $thisdir=$directories[$i];
	$thisdir=~s/\/$//g;
	open(LS,"-|") || exec "ls -rt $thisdir/$pattern";
	while(<LS>){
	    chomp;
	    my $result=$_;
	    $result=~s/^.*\/([^\/]*)$/$1/;
	    push @listing,$thisdir."/".$result;
	}
	close(LS);
    }

    return @listing;
}

sub last_time {
    my ($file)=@_;

    my $last_line_command="tail -n 1 $file";
    open(LL,"-|")||exec $last_line_command;
    my $last_line;
    while(<LL>){
	chomp;
	$last_line=$_;
    }
    close(LL);

    # get the year this log starts in
    $file=~m/\^cor\_(.*?)\-(.*?)\-.*/;
    my $year=$1;
    my $month=$2;

    my $last_line=~m/^(.*?)\-.*/;
    my $last_month=$1;
    if ($last_month<$month){
	# year has incremented
	$year++;
    }
    
    my $last_line_time=$last_line;
    $last_line_time=~s/^(.*?)\:\:.*/$1/;
    my $time_last=$year."-".$last_line_time;

    return $time_last;
}
